#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <iostream>

#pragma comment(lib, "odbc32.lib")

int main() {
    SQLHENV hEnv = nullptr;
    SQLHDBC hDbc = nullptr;
    SQLHSTMT hStmt = nullptr;
    SQLRETURN retCode;

    // 1. 初始化环境
    retCode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv);
    if (retCode != SQL_SUCCESS && retCode != SQL_SUCCESS_WITH_INFO) {
        std::cerr << "Error allocating environment handle" << std::endl;
        return -1;
    }

    retCode = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
    if (retCode != SQL_SUCCESS && retCode != SQL_SUCCESS_WITH_INFO) {
        std::cerr << "Error setting environment attribute" << std::endl;
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return -1;
    }

    // 2. 分配连接句柄
    retCode = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
    if (retCode != SQL_SUCCESS && retCode != SQL_SUCCESS_WITH_INFO) {
        std::cerr << "Error allocating connection handle" << std::endl;
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return -1;
    }

    // 3. 连接数据库
    SQLCHAR* connectionString = (SQLCHAR*)"DRIVER={SQL Server};SERVER=localhost;DATABASE=OpenAuthPro;UID=sa;PWD=1236;";

    // 使用 SQLDriverConnect 而不是 SQLConnect
    retCode = SQLDriverConnectA(hDbc, NULL, connectionString, SQL_NTS,
        NULL, 0, NULL, SQL_DRIVER_COMPLETE);
  
    if (retCode != SQL_SUCCESS && retCode != SQL_SUCCESS_WITH_INFO) {
        std::cerr << "Error connecting to database" << std::endl;
        SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return -1;
    }
    std::cout << "Connected to SQL Server successfully!" << std::endl;

    // 4. 分配语句句柄
    retCode = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);
    if (retCode != SQL_SUCCESS && retCode != SQL_SUCCESS_WITH_INFO) {
        std::cerr << "Error allocating statement handle" << std::endl;
        SQLDisconnect(hDbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return -1;
    }

    // 5. 执行查询 - 正确的参数个数
    SQLCHAR query[] = "SELECT Id, Name FROM SysUser";
    std::cout << "Executing query: " << query << std::endl;

    retCode = SQLExecDirectA(hStmt, query, SQL_NTS);

    if (retCode != SQL_SUCCESS && retCode != SQL_SUCCESS_WITH_INFO) {
        SQLCHAR sqlState[6];
        SQLCHAR errorMsg[SQL_MAX_MESSAGE_LENGTH];
        SQLINTEGER nativeError;
        SQLSMALLINT msgLength;

        SQLErrorA(hEnv, hDbc, hStmt, sqlState, &nativeError, errorMsg, sizeof(errorMsg), &msgLength);
        std::cerr << "Error executing query: " << errorMsg << " (SQL State: " << sqlState << ")" << std::endl;

        SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
        SQLDisconnect(hDbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
        SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
        return -1;
    }

    std::cout << "Query executed successfully!" << std::endl;

    // 6. 处理结果集
    char id[37];
    char name[256];
    SQLLEN idInd, nameInd;

    SQLBindCol(hStmt, 1, SQL_C_CHAR, &id, sizeof(id), &idInd);
    SQLBindCol(hStmt, 2, SQL_C_CHAR, name, sizeof(name), &nameInd);

    std::cout << "Query Results:" << std::endl;
    int rowCount = 0;

    while (SQLFetch(hStmt) == SQL_SUCCESS) {
        rowCount++;
        std::cout << "Row " << rowCount << ": ";

        if (idInd != SQL_NULL_DATA) {
            std::cout << "ID: " << id;
        }
        else {
            std::cout << "ID: NULL";
        }

        if (nameInd != SQL_NULL_DATA) {
            std::cout << ", Name: " << name << std::endl;
        }
        else {
            std::cout << ", Name: NULL" << std::endl;
        }
    }

    if (rowCount == 0) {
        std::cout << "No rows found in SysUser table." << std::endl;
    }
    else {
        std::cout << "Total rows: " << rowCount << std::endl;
    }

    // 7. 清理资源
    SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
    SQLDisconnect(hDbc);
    SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
    SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
    return 0;
}